import os
import sys
from gtk import *
from gtk.glade import XML


NAME = 0
STOCK_ID = 1
LABEL = 2
ACCELERATOR = 3
TOOLTIP = 4
CALLBACK = 5


def populate_combo(stock_combo):
    model = ListStore(str, str)
    model.append([None, "    None"])
    stock_ids = stock_list_ids()
    stock_ids.reverse()
    for id in stock_ids:
        stock_props = stock_lookup(id)
        if stock_props is not None:
            text = stock_props[1]
            head, sep, tail = text.partition("_")
            if not sep:
                markup = head
            else:
                tail = "</u>".join([tail[0], tail[1:]])
                markup = "<u>".join([head, tail])
        else:
            markup = id
        model.append([id, markup])
    pixbuf_cell = CellRendererPixbuf()
    text_cell = CellRendererText()
    pixbuf_cell.set_property("xalign", 0.0)
    text_cell.set_property("xpad", 10)
    stock_combo.pack_start(pixbuf_cell, False)
    stock_combo.pack_start(text_cell, True)
    stock_combo.add_attribute(pixbuf_cell, "stock_id", 0)
    stock_combo.add_attribute(text_cell, "markup", 1)
    stock_combo.set_model(model)


def sort_and_save(treemodel, fhandle = None):
    list = [tuple(r) for r in treemodel]
    list.sort()
    print >>fhandle, "actions_list = ["
    for t in list:
        print >>fhandle, "   ", t, ","
    print >>fhandle, "    ]"
    if fhandle is not None:
        fhandle.close()


class ActionsEditor:
    entry = []
    
    def __init__(self, actions):
        xml = XML("actions_editor.glade")
        xml.signal_autoconnect(self)
        
        name = xml.get_widget("name")
        stock_combo = xml.get_widget("stock_combo")
        label = xml.get_widget("label")
        accelerator = xml.get_widget("accelerator")
        tooltip = xml.get_widget("tooltip")
        callback = xml.get_widget("callback")
        self.entry = [name, stock_combo, label, accelerator, tooltip, callback]
        
        populate_combo(stock_combo)
        
        model = ListStore(str, str, str, str, str, str)
        for a in actions:
            model.append(a)
        
        cell = CellRendererText()
        cell.set_property("editable", True)
        col = TreeViewColumn("Actions", cell, text = 0)
        treeview = xml.get_widget("treeview1")
        treeview.append_column(col)
        treeview.set_model(model)
        selection = treeview.get_selection()
        
        cell.connect("edited", self.on_row_edited)
        selection.connect("changed", self.on_row_selected)
        
        self.model = model
        self.overwrite_dialog = xml.get_widget("overwrite_box")
        self.selection = selection
        self.statusbar = xml.get_widget("statusbar1")

    def add_entry(self, b):
        entry = ("Noname", None, None, None, None, None)
        self.model.append(entry)
        
    def delete_entry(self, b):
        model, path = self.selection.get_selected_rows()
        if path:
            row, = path
        else:
            return
        del model[row]
        for e in self.entry:
            try:
                e.set_text("")
            except AttributeError:
                e.set_active(-1)
        
    def hide_dialog(self, b):
        self.overwrite_dialog.hide()

    def on_row_edited(self, cellrenderer, path, new_text):
        for row in self.model:
            if new_text == row[NAME]:
                error = self.statusbar.get_context_id("error")
                self.statusbar.pop(error)
                self.statusbar.push(error, "Action already exists!")
                return
        self.model[path][NAME] = new_text
        
    def on_row_selected(self, selection):
        model, path = selection.get_selected_rows()
        if not path:
            return
        row, = path
        self.entry_id = row
        self.show_selected(model, row)
        
    def on_stock_combo_changed(self, combobox):
        combo_model = combobox.get_model()
        active = combobox.get_active()
        stock_id = combo_model[active][0]
        model, path = self.selection.get_selected_rows()
        if path:
            row, = path
            model[row][STOCK_ID] = stock_id
        else:
            return

    def quit(self, *args):
        sort_and_save(self.model)
        main_quit()

    def show_dialog(self, b):
        self.overwrite_dialog.show_all()

    def show_selected(self, model, row):
        for i in NAME, LABEL, ACCELERATOR, TOOLTIP, CALLBACK:
            entry = self.entry[i]
            text = model[row][i]
            if text is not None:
                entry.set_text(text)
            else:
                entry.set_text("None")
        stock_id = model[row][STOCK_ID]
        combo = self.entry[STOCK_ID]
        combo_model = combo.get_model()
        if stock_id is None:
            combo.set_active(0)
            return
        else:
            for r in combo_model:
                if r[0] == stock_id:
                    active_row, = r.path
                    combo.set_active(active_row)
                    return
        combo.set_active(-1)
        warning = self.statusbar.get_context_id("warning")
        self.statusbar.pop(warning)
        self.statusbar.push(warning, "Warning: 'stock-id' not found")

    def update_entry(self, entry, *args):
        text = entry.get_text().strip()
        if text == "":
            text = None
            entry.set_text("None")
        model, path = self.selection.get_selected_rows()
        row, = path
        col = entry.get_name()
        if col == "label":
            self.model[row][LABEL] = text
        elif col == "accelerator":
            self.model[row][ACCELERATOR] = text
        elif col == "tooltip":
            self.model[row][TOOLTIP] = text
        elif col == "callback":
            self.model[row][CALLBACK] = text

    def write_actions(self, b):
        actions = open("actions.py", "w")
        sort_and_save(self.model, actions)
        message = self.statusbar.get_context_id("message")
        self.statusbar.pop(message)
        self.statusbar.push(message, "Actions saved")
        

if __name__ == "__main__":
    import actions
    ae = ActionsEditor(actions.actions_list)
    main()
